package gui;

import java.awt.Graphics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.swing.*;

import components.register.RegisterGroup;

public class RegisterLightGroup extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	int[] statusOfLight;
	int bitNum;
	Light[] lightGroup = null;
	String regName = "";
	boolean editable = false;


	// position of the light group on the control panel
	int xPosition = 0;
	int yPosition = 0;

	private static RegisterGroup regs = RegisterGroup.getInstance();

	public RegisterLightGroup(String regName) {

		this.regName = regName;
		String s = "get" + regName;

		Method m;
		try {
			m = regs.getClass().getMethod(s, null);
			statusOfLight = (int[]) m.invoke(regs);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			/************ R1 - R4 ************/
			// r1 -> getGPR(0);
			// r2 -> getGPR(1);
			// r3 -> getGPR(2);
			// r4 -> getGPR(3);

			int regNum = Character.getNumericValue(regName.toCharArray()[1]) - 1;
			s = "getGPR";

			/******/
			try {
				m = regs.getClass().getMethod(s, int.class);
				statusOfLight = (int[]) m.invoke(regs, regNum);
			} catch (NoSuchMethodException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (SecurityException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();

			} catch (IllegalAccessException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			/*******/
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		bitNum = statusOfLight.length;

		lightGroup = new Light[bitNum];
		for (int i = 0; i < bitNum; i++) {
			if (bitNum != 16)
				lightGroup[i] = new Light(bitNum);
			else
				lightGroup[i] = new Light();
		}
		this.setVisible(true);
		this.setOpaque(false);
		this.repaint();
	}

	/****
	 * call the get function of corresponding register.
	 */
	public void refresh() {
		String s = "get" + regName;
		Method m;
		try {
			m = regs.getClass().getMethod(s, null);
			statusOfLight = (int[]) m.invoke(regs);

			for (int i = 0; i < bitNum; i++) {
				if (statusOfLight[i] == 1)
					lightGroup[i].setIcon(lightGroup[i].icon2);
				else
					lightGroup[i].setIcon(lightGroup[i].icon1);
				lightGroup[i].editable = this.editable;
			}
	//		System.out.println(Arrays.toString(statusOfLight));

			//
		} catch (NoSuchMethodException e) {
			/************ R1 - R4 ************/
			// r1 -> getGPR(0);
			// r2 -> getGPR(1);
			// r3 -> getGPR(2);
			// r4 -> getGPR(3);

			int regNum = Character.getNumericValue(regName.toCharArray()[1]) - 1;
			s = "getGPR";

			/******/
			try {
				m = regs.getClass().getMethod(s, int.class);
				statusOfLight = (int[]) m.invoke(regs, regNum);
			} catch (NoSuchMethodException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (SecurityException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();

			} catch (IllegalAccessException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			/*******/
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// change the values in registers by clicking lights.

	/***
	 * call the set function of the corresponding register,
	 * 
	 * @param val
	 *            is the value you want to set into the target register.
	 */
	public void change(int[] val) {
		if (!editable)
			return;

		String s = "set" + regName;
		Class<int[]> type = int[].class;
		Method m;
		try {
			m = regs.getClass().getMethod(s, type);
			m.invoke(regs, (int[]) val);
		} catch (NoSuchMethodException e) {
			/************ R1 - R4 ************/
			// r1 -> getGPR(0);
			// r2 -> getGPR(1);
			// r3 -> getGPR(2);
			// r4 -> getGPR(3);

			int regNum = Character.getNumericValue(regName.toCharArray()[1]) - 1;
			s = "setGPR";

			/******/
			try {
				m = regs.getClass().getMethod(s, type, int.class);
				statusOfLight = (int[]) m.invoke(regs, val, regNum);
			} catch (NoSuchMethodException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (SecurityException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();

			} catch (IllegalAccessException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e2) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			/*******/
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setEditable(boolean editable) {
		// TODO Auto-generated method stub
		this.editable = editable;
	}

	public void setPosition(int x, int y) {
		this.xPosition = x;
		this.yPosition = y;

		this.setLayout(null);
		for (int i = 0; i < bitNum; i++) {

			this.add(lightGroup[i]);
			lightGroup[i].editable = this.editable;
			lightGroup[i].setBounds(0 + i * 18, 0, 10, 10);
		}
		this.setBounds(xPosition, yPosition, 10 + bitNum * 18, 10);
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);

	}

	// a demonstration main function
	// public static void main(String[] args) throws IOException {
	//
	// RegisterLightGroup PCLights = new RegisterLightGroup("PC");
	// PCLights.setOpaque(false);
	// PCLights.setPosition(52, 203);
	// String path = "Images/background.jpg";
	// BufferedImage image = ImageIO.read(new File(path));
	// // ControlPanel cpanel = new ControlPanel(image);
	// JFrame f = new JFrame();
	// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	// f.getContentPane().setLayout(null);
	// f.getContentPane().add(PCLights);
	// f.setSize(732, 518);
	// f.setLocation(150, 50);
	// f.setVisible(true);
	//
	// // initialize a light group, e.g., a PC.
	//
	// // initialize the value in PC
	// regs.setPC(new int[] { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 });
	//
	// // refresh the status of PC lights,
	// PCLights.refresh();
	//
	// // assume user clicked on the lights and want to change the value of PC
	// PCLights.change(new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
	// 0, 0 });
	//
	// // refresh the lights, get current PC.
	// PCLights.refresh();
	// }
}
